<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>仪表盘</title>
  </head>
  <body>
    <div id="pie"></div>
    <script>
      const sentiment = 2.5,
        totalSentiment = 5,
        bgColor = "rgba(50,111,240,0.1)",
        color = "#326FF0",
        strokeWidth = 16,
        width = 120,
        height = 60;

      const getCircleCommon = (w, h, strokeWidth) => {
        const half = strokeWidth / 2;
        const hR = h - half;
        const wR = (w - half) / 2;
        const r = Math.min(hR, wR);

        const x = w / 2;
        const y = h + half;
        return {
          x,
          y,
          r,
        };
      };

      const getStartEndPointer = ({ x, y, r }) => {
        const beginPointer = { x: x - r, y: y };
        const endPointer = { x: x + r, y: y };

        return {
          beginPointer,
          endPointer,
        };
      };

      const { d, dashWidth, x, y, r, beginPointer } = (() => {
        const { x, y, r } = getCircleCommon(width, height, strokeWidth);
        const { beginPointer, endPointer } = getStartEndPointer({ x, y, r });
        const d = `M ${beginPointer.x} ${beginPointer.y} A ${r} ${r} 0 0 1 ${endPointer.x} ${endPointer.y}`;
        const dashWidth = Math.ceil(Math.PI * r);

        return {
          d: d,
          dashWidth,
          strokeWidth,
          width,
          height,
          x,
          y,
          r,
          beginPointer,
        };
      })();

      const { strokeDashoffset, proportionDeg } = (() => {
        let value = sentiment / totalSentiment;
        value = 1 - (value > 1 ? 1 : value);

        return {
          strokeDashoffset: dashWidth * value,
          proportionDeg: 1 - value,
        };
      })();

      // 计算斜线的相关参数
      const { from, to, strokeDash, ...lineSentiment } = (() => {
        const center = x + " " + y;
        const deg = 180 * proportionDeg;

        return {
          x1: beginPointer.x - strokeWidth / 2 - 2,
          y1: beginPointer.y,
          x2: x,
          y2: y,
          transform: `rotate(${deg} ${center})`,
          from: `${0} ${center}`,
          to: `${deg} ${center}`,
          strokeDash: strokeWidth + 4,
        };
      })();

      document.getElementById("pie").innerHTML = `
        <svg width="${width}" height="${height + 10 + strokeWidth / 2}">
        <path
          d="${d}"
          stroke="${bgColor}"
          stroke-width="${strokeWidth}"
          fill="none"
          vector-effect="non-scaling-stroke"
        />
        <path
          d="${d}"
          stroke="${color}"
          stroke-width="${strokeWidth}"
          stroke-dasharray="${dashWidth} ${dashWidth}"
          stroke-dashoffset="${strokeDashoffset}"
          fill="none"
          vector-effect="non-scaling-stroke"
        >
          <animate
            attributeType="XML"
            attributeName="stroke-dashoffset"
            from="${dashWidth}"
            to="${strokeDashoffset}"
            dur="1s"
            calcMode="paced"
            repeatCount="1"
          />
        </path>

        <line
          x1="${lineSentiment.x1}"
          y1="${lineSentiment.y1}"
          x2="${lineSentiment.x2}"
          y2="${lineSentiment.y2}"
          transform="${lineSentiment.transform}"
          stroke="${color}"
          stroke-dasharray="${strokeDash} ${r}"
          stroke-width="5"
          stroke-linecap="round"
        >
          <animateTransform
            attributeName="transform"
            type="rotate"
            from="${from}"
            to="${to}"
            dur="1s"
            calcMode="paced"
            repeatCount="1"
          />
        </line>
        <text
          style="font-size: 20px;font-weight: 700"
          x="${x}"
          text-anchor="middle"
          y="${y + 5}"
        >
          ${sentiment}
        </text>
      </svg>`;
    </script>
  </body>
</html>
